﻿using System;
using System.IO;
using System.Net;
using CuteRibs.D3Armory.Models;
using CuteRibs.D3Armory.Resources;
using ICSharpCode.SharpZipLib.GZip;
using Microsoft.Phone.Net.NetworkInformation;
using Newtonsoft.Json;

namespace CuteRibs.D3Armory
{
	public class D3Client
	{
		#region tooltipHtml
		private static readonly string tooltipHtml = @"
<html xmlns=""http://www.w3.org/1999/xhtml"">
<head>
	<title></title>
	<meta http-equiv=""X-UA-Compatible"" content=""IE=edge,chrome=1"" />
	<meta name=""viewport"" content=""width=354"" />
	<link href=""http://{0}/d3/static/css/tooltips.css"" rel=""stylesheet"" type=""text/css"" />
	<script type=""text/javascript"">
		window.onload = function () {{
			var content = document.getElementById('content');
			window.external.Notify(content.scrollHeight.toString());
		}}
	</script>
</head>
<body style=""background-color: #000000; margin: 0; padding: 0;"">
<div id=""content"">
{1}
</div>
</body>
</html>
"; 
		#endregion

		private static readonly string realmStatusUri = "http://{0}/d3/status";
		private static readonly string profileUri = "http://{0}/api/d3/profile/{1}/";
		private static readonly string heroUri = "http://{0}/api/d3/profile/{1}/hero/{2}";

		private static readonly string itemTooltipUri = "http://{0}/d3/tooltip/{1}";
		private static readonly string runeTooltipUri = "http://{0}/d3/tooltip/{1}";
		private static readonly string skillTooltipUri = "http://{0}/d3/tooltip/{1}?runeType={2}";

		private HttpWebRequest request;
		private HttpWebResponse response;

		public void GetRealmStatus(Action<string> callback)
		{
			string uri = string.Format(realmStatusUri, App.GetDomain());
			this.SendRequest(uri, callback);
		}

		public void GetProfile(Realm realm, string battleTag, Action<Profile> callback)
		{
			string uri = string.Format(profileUri, App.GetDomain(realm), battleTag);
			Action<string> action = delegate(string json)
			{
				var profile = JsonConvert.DeserializeObject<Profile>(json);
				profile.Realm = realm;
				callback(profile);
			};
			this.SendRequest(uri, action);
		}

		public void GetHero(Realm realm, string battleTag, uint heroId, Action<Hero> callback)
		{
			string uri = string.Format(heroUri, App.GetDomain(realm), battleTag, heroId);
			Action<string> action = delegate(string json)
			{
				var hero = JsonConvert.DeserializeObject<Hero>(json);
				callback(hero);
			};
			this.SendRequest(uri, action);
		}

		#region TooltipHtml
		public void GetItemTooltipHtml(string tooltipParams, Action<string> callback, bool refresh = false)
		{
			string domain = App.GetDomain();
			string uri = string.Format(itemTooltipUri, domain, tooltipParams);
			this.GetTooltipHtml(domain, uri, callback, refresh);
		}

		public void GetSkillTooltipHtml(string tooltipParams, string runeType, Action<string> callback, bool refresh = false)
		{
			string domain = App.GetDomain();
			string uri = string.Format(skillTooltipUri, domain, tooltipParams, runeType);
			this.GetTooltipHtml(domain, uri, callback, refresh);
		}

		public void GetRuneTooltipHtml(string tooltipParams, Action<string> callback, bool refresh = false)
		{
			string domain = App.GetDomain();
			string uri = string.Format(runeTooltipUri, domain, tooltipParams);
			this.GetTooltipHtml(domain, uri, callback, refresh);
		}

		private void GetTooltipHtml(string domain, string uri, Action<string> callback, bool refresh)
		{
			if (!refresh)
			{
				var html = App.GetTooltipHtml(uri);

				if (!string.IsNullOrWhiteSpace(html))
				{
					callback(html);
					return;
				}
			}

			Action<string> action = delegate(string text)
			{
				if (string.IsNullOrWhiteSpace(text))
				{
					callback(null);
				}
				else
				{
					var html = Helper.EncodeHtmlString(string.Format(tooltipHtml, domain, text));
					App.SaveTooltipHtml(uri, html);
					callback(html);
				}
			};

			this.SendRequest(uri, action);
		} 
		#endregion

		private void SendRequest(string uri, Action<string> callback)
		{
			if (NetworkInterface.GetIsNetworkAvailable())
			{
				this.request = HttpWebRequest.CreateHttp(uri);
				this.request.Method = "GET";
				this.request.BeginGetResponse(new AsyncCallback(this.RequestCallback), callback);
			}
			else
			{
				App.ShowAlert(AppRes.MsgNoNetwork);
			}
		}

		private void RequestCallback(IAsyncResult asyncResult)
		{
			var callback = asyncResult.AsyncState as Action<string>;

			try
			{
				this.response = this.request.EndGetResponse(asyncResult) as HttpWebResponse;
			}
			catch (WebException ex)
			{
				this.response = ex.Response as HttpWebResponse;
			}

			Stream responseStream;
			string text;

			if (this.response.Headers[HttpRequestHeader.ContentEncoding] == "gzip")
			{
				responseStream = new GZipInputStream(response.GetResponseStream());
			}
			else
			{
				responseStream = response.GetResponseStream();
			}

			using (StreamReader reader = new StreamReader(responseStream))
			{
				text = reader.ReadToEnd();
			}

			responseStream.Close();
			callback(text);
		}
	}
}
